package com.christina.engine.processing.model;

import com.christina.engine.context.model.ConversationContext;
import com.christina.engine.context.model.UserContext;
import com.christina.engine.decision.model.DecisionResult;
import com.christina.engine.intent.model.Intent;
import com.christina.service.application.model.UnifiedRequest;
import com.christina.service.application.model.UnifiedResponse;
import com.christina.service.application.model.UnifiedResponse.UnifiedResponseBuilder;
import lombok.Getter;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 处理上下文数据模型
 * 包含请求处理过程中的所有相关信息和状态
 */
@Getter
public class ProcessingContext {
    
    private final String requestId;
    private final Long userId;
    private final String sessionId;
    private final UnifiedRequest originalRequest;
    private final UnifiedResponseBuilder responseBuilder;
    private volatile Intent recognizedIntent;
    private volatile DecisionResult decisionResult;
    private volatile UserContext userContext;
    private volatile ConversationContext conversationContext;
    private final Map<String, Object> processingData;
    private final List<ProcessingEvent> events;
    private volatile String currentState;
    private final LocalDateTime startTime;
    private volatile LocalDateTime lastUpdateTime;
    
    // 私有构造函数，强制使用Builder
    private ProcessingContext(Builder builder) {
        this.requestId = builder.requestId;
        this.userId = builder.userId;
        this.sessionId = builder.sessionId;
        this.originalRequest = builder.originalRequest;
        this.responseBuilder = builder.responseBuilder;
        this.recognizedIntent = builder.recognizedIntent;
        this.decisionResult = builder.decisionResult;
        this.userContext = builder.userContext;
        this.conversationContext = builder.conversationContext;
        this.processingData = new ConcurrentHashMap<>(builder.processingData);
        this.events = Collections.synchronizedList(new ArrayList<>(builder.events));
        this.currentState = builder.currentState;
        this.startTime = builder.startTime != null ? builder.startTime : LocalDateTime.now();
        this.lastUpdateTime = LocalDateTime.now();
    }
    
    // 自定义getter方法返回防御性拷贝
    public Map<String, Object> getProcessingData() { 
        synchronized (processingData) {
            return new HashMap<>(processingData); 
        }
    }
    
    public String getContextId() {
        return requestId;
    }
    
    public String getLocation() {
        return (String) processingData.get("location");
    }
    
    public List<ProcessingEvent> getEvents() { 
        synchronized (events) {
            return new ArrayList<>(events); 
        }
    }
    
    // 状态跟踪方法
    public void updateState(String newState) {
        this.currentState = newState;
        this.lastUpdateTime = LocalDateTime.now();
        addEvent(ProcessingEvent.stateChanged(newState));
    }
    
    // 处理数据管理方法
    public void setProcessingData(String key, Object value) {
        this.processingData.put(key, value);
        this.lastUpdateTime = LocalDateTime.now();
    }
    
    public <T> T getProcessingData(String key, Class<T> type) {
        Object value = processingData.get(key);
        if (type.isInstance(value)) {
            return type.cast(value);
        }
        return null;
    }
    
    public boolean hasProcessingData(String key) {
        return processingData.containsKey(key);
    }
    
    public void removeProcessingData(String key) {
        processingData.remove(key);
        this.lastUpdateTime = LocalDateTime.now();
    }
    
    public void clearProcessingData() {
        processingData.clear();
        this.lastUpdateTime = LocalDateTime.now();
    }
    
    public int getProcessingDataSize() {
        return processingData.size();
    }
    
    // 事件管理方法
    public void addEvent(ProcessingEvent event) {
        this.events.add(event);
        this.lastUpdateTime = LocalDateTime.now();
    }
    
    public List<ProcessingEvent> getEventsByType(ProcessingEventType type) {
        synchronized (events) {
            return events.stream()
                    .filter(event -> event.getType() == type)
                    .toList();
        }
    }
    
    public int getEventCount() {
        synchronized (events) {
            return events.size();
        }
    }
    
    public void clearEvents() {
        synchronized (events) {
            events.clear();
        }
        this.lastUpdateTime = LocalDateTime.now();
    }
    
    // 上下文更新方法
    public void setRecognizedIntent(Intent intent) {
        this.recognizedIntent = intent;
        this.lastUpdateTime = LocalDateTime.now();
        addEvent(ProcessingEvent.intentRecognized(intent));
    }
    
    public void setDecisionResult(DecisionResult result) {
        this.decisionResult = result;
        this.lastUpdateTime = LocalDateTime.now();
        addEvent(ProcessingEvent.decisionMade(result));
    }
    
    public void setUserContext(UserContext userContext) {
        this.userContext = userContext;
        this.lastUpdateTime = LocalDateTime.now();
    }
    
    public void setConversationContext(ConversationContext conversationContext) {
        this.conversationContext = conversationContext;
        this.lastUpdateTime = LocalDateTime.now();
    }
    
    // Builder模式实现
    public static class Builder {
        private String requestId;
        private Long userId;
        private String sessionId;
        private UnifiedRequest originalRequest;
        private UnifiedResponseBuilder responseBuilder;
        private Intent recognizedIntent;
        private DecisionResult decisionResult;
        private UserContext userContext;
        private ConversationContext conversationContext;
        private Map<String, Object> processingData = new HashMap<>();
        private List<ProcessingEvent> events = new ArrayList<>();
        private String currentState = "INITIAL";
        private LocalDateTime startTime;
        
        public Builder requestId(String requestId) {
            this.requestId = requestId;
            return this;
        }
        
        public Builder userId(Long userId) {
            this.userId = userId;
            return this;
        }
        
        public Builder sessionId(String sessionId) {
            this.sessionId = sessionId;
            return this;
        }
        
        public Builder originalRequest(UnifiedRequest request) {
            this.originalRequest = request;
            return this;
        }
        
        public Builder responseBuilder(UnifiedResponseBuilder responseBuilder) {
            this.responseBuilder = responseBuilder;
            return this;
        }
        
        public Builder recognizedIntent(Intent intent) {
            this.recognizedIntent = intent;
            return this;
        }
        
        public Builder decisionResult(DecisionResult result) {
            this.decisionResult = result;
            return this;
        }
        
        public Builder userContext(UserContext userContext) {
            this.userContext = userContext;
            return this;
        }
        
        public Builder conversationContext(ConversationContext conversationContext) {
            this.conversationContext = conversationContext;
            return this;
        }
        
        public Builder processingData(String key, Object value) {
            this.processingData.put(key, value);
            return this;
        }
        
        public Builder processingData(Map<String, Object> data) {
            if (data != null) {
                this.processingData.putAll(data);
            }
            return this;
        }
        
        public Builder addEvent(ProcessingEvent event) {
            this.events.add(event);
            return this;
        }
        
        public Builder currentState(String state) {
            this.currentState = state;
            return this;
        }
        
        public Builder startTime(LocalDateTime startTime) {
            this.startTime = startTime;
            return this;
        }
        
        public ProcessingContext build() {
            // 验证必要字段
            if (requestId == null || requestId.trim().isEmpty()) {
                throw new IllegalArgumentException("Request ID cannot be null or empty");
            }
            if (originalRequest == null) {
                throw new IllegalArgumentException("Original request cannot be null");
            }
            if (responseBuilder == null) {
                this.responseBuilder = UnifiedResponse.builder();
            }
            
            // 创建防御性拷贝
            this.processingData = new HashMap<>(this.processingData);
            this.events = new ArrayList<>(this.events);
            
            return new ProcessingContext(this);
        }
    }
    
    // 静态工厂方法
    public static Builder builder() {
        return new Builder();
    }
    
    public static ProcessingContext fromRequest(UnifiedRequest request) {
        return builder()
                .requestId(UUID.randomUUID().toString())
                .userId(request.getUserId())
                .sessionId(request.getSessionId())
                .originalRequest(request)
                .responseBuilder(UnifiedResponse.builder())
                .build();
    }
    
    @Override
    public String toString() {
        return "ProcessingContext{" +
                "requestId='" + requestId + '\'' +
                ", userId=" + userId +
                ", sessionId='" + sessionId + '\'' +
                ", currentState='" + currentState + '\'' +
                ", startTime=" + startTime +
                ", eventsCount=" + getEventCount() +
                ", processingDataKeys=" + processingData.keySet() +
                '}';
    }
}